#include <iostream>
#include <pthread.h>
#include <ctime>
#include <cstdlib>
#include <unistd.h>
#include <cstring>
#include <vector>
#include "RingBuffer.hpp"
#include "Task.hpp"

#define PSIZE 3
#define CSIZE 2

//生产者方法
const char str[] = "+-*/%!@";
void* Productor(void* arg)
{
    Productor_C<Task<int>>* PD  = static_cast<Productor_C<Task<int>>*>(arg);
    std::string name = PD->GetName();
    while(true)
    {
        //生产数据
        int data1 = rand() % 10;
        int data2 = rand() % 10;
        char oper = str[rand() % strlen(str)];
        Task<int> task{data1, data2, oper};

        //插入
        PD->_RB->Push(task);

        //打印日志
        std::cout << name << " : ";
        task.TaskPrint();
        
    }
}

//消费者方法
void* Consumer(void* arg)
{
    Consumer_C<Task<int>>* CS = static_cast<Consumer_C<Task<int>>*>(arg);
    std::string name = CS->GetName();
    while(true)
    {
        //拿数据
        Task<int> task;
        CS->_RB->Pop(&task);

        //处理数据
        task.Run();

        //打印日志
        std::cout << name << " : ";
        task.ResultPrint();
        sleep(1);
    }
    
}
int main()
{
    srand(time(nullptr) ^ pthread_self());

    ////////////////多生产者消费者模型//////////////////

    //定义多生产者，多消费者
    std::vector<pthread_t> productors(PSIZE);
    std::vector<pthread_t> consumers(CSIZE);

    //定义环形队列资源
    RingBuffer<Task<int>>* RB = new RingBuffer<Task<int>>;
    Productor_C<Task<int>> PD(RB);
    Consumer_C<Task<int>> CS(RB);

    //让多生产者和消费者执行方法
    for(auto& e : productors) pthread_create(&e, nullptr, Productor, &PD);
    for(auto& e : consumers)  pthread_create(&e, nullptr, Consumer, &CS);

    //等待上述线程
    for(auto& e : productors) pthread_join(e, nullptr);
    for(auto& e : consumers)  pthread_join(e ,nullptr);

    ////////////////单生产者消费者模型///////////////////
    /*
        //定义生产者和消费者
        pthread_t productor;
        pthread_t consumer;
        //定义一份环形队列资源
        RingBuffer<Task<int>>* RB = new RingBuffer<Task<int>>;
        //让生产者和消费者执行对应的方法
        pthread_create(&productor, nullptr, Productor, RB);
        pthread_create(&consumer, nullptr, Consumer, RB); 
        //主线程等待两个新线程
        pthread_join(productor, nullptr);
        pthread_join(consumer, nullptr);
    */
    return 0;
}